;######################################## RVAToOffset (Iczelion) ############################################################### ; Cette procédure transforme un RVA en une adresse fichier. ; Un RVA c'est pas une adresse. Un RVA c'est une distance. Quand un programme tourne, il est recopié quelquepart en mémoire (on ne sait pas précisément où) ; on connait juste l'endroit de départ où il se trouve (pFileMap = début du programme en mémoire) donc quand le programme utilise des addresse il préfère utiliser ; des adresses en se servant de son point de départ (les RVA) et non pas des adresses Absolues. ; Par contre on peut aussi voir ce système (ce programma) d'une autre façon (Celle de HexWorkShop, W32Dasm...). en se disant que ce progamma est un fichier ; qui débute en 00400000h (en 10000000h pour les DLL) et donc les RVA d'antant doivent être transformés en véritables offsets pour fichiers. C'est ce qui est fait ici. ; ; RVAToOffset PROC uses edi esi edx ecx pFileMap:DWORD,RVA:DWORD ; RVA est une adresse RVA provenant du PE Header -- pFileMap est l'adresse de début du programme en mémoire mov esi,pFileMap ; assume esi:ptr IMAGE_DOS_HEADER ; add esi,[esi].e_lfanew ; assume esi:ptr IMAGE_NT_HEADERS ; ESI repésente la structure IMAGE_NT_HEADERS mov edi,RVA ; ; EDI == RVA mov edx,esi ; add edx,sizeof IMAGE_NT_HEADERS ; mov cx,[esi].FileHeader.NumberOfSections ; movzx ecx,cx ; assume edx:ptr IMAGE_SECTION_HEADER ; EDX représente la structure IMAGE_SECTION_HEADER .while ecx>0 ; check all sections ; On entre dans les sections en les listant de la dernière à la première .if edi>=[edx].VirtualAddress ; on entre dans ce if à chaque fois que notre RVA >= au début de cette section mov eax,[edx].VirtualAddress ; eax == début section add eax,[edx].SizeOfRawData ; eax == fin section .if edi NOMBRE HEXA ############################################ Char2Hexa proc uses ebx ecx edx addr_string:DWORD LOCAL NombreDD:DWORD LOCAL NoChar:DWORD mov NombreDD, 0 mov NoChar, 0 xor ebx, ebx xor ecx, ecx xor edx, edx mov eax, addr_string Saut@1: inc ecx cmp byte ptr [eax+ecx], 0 jne Saut@1 ; ecx contient le nombre de caractères. inc ecx Saut@New: dec ecx push ecx mov eax, addr_string ; eax pointe sur le début de la chaine de chiffres add eax, NoChar mov bl, byte ptr [eax] .if bl>=30h && bl<=39h ; Converti les caractères en chiffres Hexa ; bl = f(cara) sub bl, 30h ; ex : 5 (char) --> 5 (hexa) ; bl = 0fh .else ; ; bl = 15d sub bl, 57h ; ex : f (char) --> f (hexa) = 15 (déci) .endif ; bl = le chiffre (format hex) ; bl = le chiffre (format hex) mov dx, bx mov dh, 0 mov bh, cl ; bh = niveau de ce chiffre dec bh xor eax, eax xor cl, cl mov ax, dx Saut@2: cmp bh,0 je Saut@3 dec bh add cl, 4 jmp Saut@2 Saut@3: rol eax, cl ; eax contient la valeur du rang ; exemple pour 2658 (caractère) ; au rang 3, eax vaut 600 ; au rang 4, eax vaut 2000 add NombreDD, eax pop ecx inc NoChar cmp ecx, 1 jne Saut@New mov eax, NombreDD ret Char2Hexa ENDP ; ############################################ CHAINE HEXA --> NOMBRE HEXA ############################################ ; ############################################ NOMBRE HEXA --> CHAINE HEXA ############################################ Hexa2Char proc uses ebx ecx edx nombreHexa:DWORD mov eax, nombreHexa invoke wsprintf, addr nombreHChar, addr formatHexa, eax ret Hexa2Char endp ; en retour "nombreHChar" est une chaine de caractères représentant un nombre hexadécimal ; ############################################ NOMBRE HEXA --> CHAINE HEXA ############################################ ; ############################################ NOMBRE DECI --> CHAINE DECI ############################################ Deci2Char proc uses ebx ecx edx nombreDeci:DWORD mov eax, nombreDeci invoke wsprintf, addr nombreHChar, addr formatDeci, eax ret Deci2Char endp ; en retour "nombreHChar" est une chaine de caractères représentant un nombredécimal ; ############################################ NOMBRE HEXA --> CHAINE DECI ############################################